﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Core.Model;
using Core.Model.Transmit;
using Core.Transmit;
using DataServer.Config;

namespace DataServer.View.Transmit
{
    /// <summary>
    /// DataItemEdit.xaml 的交互逻辑
    /// </summary>
    public partial class TransmitDataPanel
    {
        private TransmitDevice _device;
        public TransmitDevice Device
        {
            get { return _device; }
        }
        private static readonly Dictionary<string,TransmitDeviceProtocol> _devProtocols = new Dictionary<string, TransmitDeviceProtocol>();
        private readonly ObservableCollection<Channel> _channels = new ObservableCollection<Channel>();
        private readonly ObservableCollection<Device> _devices = new ObservableCollection<Device>();
        private readonly ObservableCollection<DataItem> _dataItems = new ObservableCollection<DataItem>();
        private Channel _selectChannel;
        private Device _selectDevice;
        private DataItem _selectDataItem;
        private TransmitData _selectTransmitData;
        private readonly ObservableCollection<TransmitData> _transmitDataItems = new ObservableCollection<TransmitData>();

        private bool _isRunning = true;
        
        public TransmitDataPanel()
        {
            InitializeComponent();
            _gridDataItem.DataContext = this;
            _gridModify.Visibility = _isRunning ? Visibility.Collapsed : Visibility.Visible;
            menuDataitem.IsEnabled = !_isRunning;
            this.Loaded += TransmitDataPanel_Loaded;
        }

        private void TransmitDataPanel_Loaded(object sender, RoutedEventArgs e)
        {
            _channels.Clear();
            List<Channel> channels = AppManager.ChannelDao.GetEntities();
            if (channels != null)
            {
                foreach (Channel ch in channels)
                {
                    _channels.Add(ch);
                }
            }
            cbbChannel.ItemsSource = _channels;
        }

        #region 数据选择处理

        public void UpdateDataItems(TransmitDevice device)
        {
            if (_isRunning != AppManager.IsRunning)
            {
                _isRunning = AppManager.IsRunning;
                _gridModify.Visibility = _isRunning?Visibility.Collapsed : Visibility.Visible;
               
                menuDataitem.IsEnabled = !_isRunning;
            }

            List<TransmitData> dataItems;
            if (AppManager.IsRunning)
            {
                 dataItems = AppManager.TransmitDataDao.GetDataItemsByDevId(device.Id);
                _transmitDataItems.Clear();
                if (dataItems.Count > 0)
                {
                    foreach (TransmitData item in dataItems)
                    {
                        _transmitDataItems.Add(item);
                    }
                }

                _gridDataItem.ItemsSource = _transmitDataItems;
                return;
            }
            
            if (_device != null && _transmitDataItems.Count > 0)
            {
                for (int i = 0; i < _transmitDataItems.Count; i++)
                {
                    _transmitDataItems[i].Position = i;
                }
                List<TransmitData> items = _transmitDataItems.ToList();
                items = SerializeItems(items);
                Core.Global.DataAccess.SaveTransmitDatas(_device.Id, items);
            }
            _transmitDataItems.Clear();
            _device = device;
            if (_device != null)
            {
                dataItems = Core.Global.DataAccess.GetTransmitData(_device.Id);
                dataItems = DeSerializeItems(dataItems);
                if (dataItems?.Count > 0)
                {
                    foreach (TransmitData item in dataItems)
                    {
                        _transmitDataItems.Add(item);
                    }
                }
            }
            _gridDataItem.ItemsSource = _transmitDataItems;
        }
       
        #endregion

        #region 加载保存数据

        private void BtnLoadDataItem_OnClick(object sender, RoutedEventArgs e)
        {
            if (_device != null)
            {
                _transmitDataItems.Clear();
                List<TransmitData> dataItems = Core.Global.DataAccess.GetTransmitData(_device.Id);
                dataItems = DeSerializeItems(dataItems);
                if (dataItems.Count > 0)
                {
                    foreach (TransmitData item in dataItems)
                    {
                        _transmitDataItems.Add(item);
                    }
                }
                _gridDataItem.ItemsSource = _transmitDataItems;
            }
        }

        private void BtnSaveDataItem_OnClick(object sender, RoutedEventArgs e)
        {
            if (_device != null)
            {
                for (int i = 0; i < _transmitDataItems.Count; i++)
                {
                    _transmitDataItems[i].Position = i;
                }
                List<TransmitData> items = _transmitDataItems.ToList();
                items = SerializeItems(items);
                if (Core.Global.DataAccess.SaveTransmitDatas(_device.Id, items))
                {
                    MessageBox.Show("保存成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }
            }
            MessageBox.Show("保存失败!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
        }


        #endregion

        #region 添加删除移动数据项

        private void MiAddDataItem_OnClick(object sender, RoutedEventArgs e)
        {
            if (_device == null)
            {
                MessageBox.Show("添加失败,请先选择设备!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            if (string.IsNullOrEmpty(_device.Protocol))
            {
                MessageBox.Show("添加失败,请先选择设备通信协议!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            TransmitData insert;
            if (_gridDataItem.SelectedItem is TransmitData sel)
            {
                int index = _transmitDataItems.IndexOf(sel);
                insert = new TransmitData(sel);
                insert = DecorateItem(insert);
                _transmitDataItems.Insert(index + 1, insert);
            }
            else
            {
                insert = new TransmitData("新数据项", _device.Id);
                insert = DecorateItem(insert);
                _transmitDataItems.Add(insert);
            }
            _gridDataItem.SelectedItem = insert;
        }
        private void MiDelDataItem_OnClick(object sender, RoutedEventArgs e)
        {
            int count = _gridDataItem.SelectedItems.Count, index = 0;
            while (_gridDataItem.SelectedItems.Count > 0)
            {
                if (_gridDataItem.SelectedItems[0] is TransmitData del) _transmitDataItems.Remove(del);
                index++;
                if (index >= count)
                    break;
            }
        }
        private void BtnAddDataItem_OnClick(object sender, RoutedEventArgs e)
        {
            if (_device == null)
            {
                MessageBox.Show("添加失败,请先选择设备!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            if (string.IsNullOrEmpty(_device.Protocol))
            {
                MessageBox.Show("添加失败,请先选择设备通信协议!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            var sel = _transmitDataItems.Count > 0 ? _transmitDataItems[_transmitDataItems.Count - 1] : null;
           
            if (sel != null)
            {
                int index = _transmitDataItems.IndexOf(sel);
                sel = new TransmitData(sel);
                sel = DecorateItem(sel);
                _transmitDataItems.Insert(index + 1, sel);
            }
            else
            {
                sel = new TransmitData("新数据项", _device.Id);
                sel = DecorateItem(sel);
                _transmitDataItems.Add(sel);
            }
            _gridDataItem.SelectedItem = _transmitDataItems[_transmitDataItems.Count - 1];
        }

        private void BtnBatchAdd_OnClick(object sender, RoutedEventArgs e)
        {
            if (_device == null)
            {
                MessageBox.Show("添加失败,请先选择设备!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            if (string.IsNullOrEmpty(_device.Protocol))
            {
                MessageBox.Show("添加失败,请先选择设备通信协议!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
            TransmitDataModify view = new TransmitDataModify(_transmitDataItems.ToList());
            if (view.ShowDialog() == true)
            {
                var sel = _transmitDataItems.Count > 0 ? _transmitDataItems[_transmitDataItems.Count - 1] : null;
                foreach (TransmitDataModel dataModel in view.NewSelected)
                {
                    if (sel != null)
                    {
                        int index = _transmitDataItems.IndexOf(sel);
                        sel = new TransmitData(sel);
                        sel.Name = dataModel.Name;
                        sel.SourceId = dataModel.Id;
                        sel.Coefficient = dataModel.Radio;
                        sel.PhyType = dataModel.IsSignal ? PhyType.信号量 : PhyType.模拟量;
                        sel = DecorateItem(sel);
                        _transmitDataItems.Insert(index + 1, sel);
                    }
                    else
                    {
                        sel = new TransmitData("新数据项", _device.Id);
                        sel.Name = dataModel.Name;
                        sel.SourceId = dataModel.Id;
                        sel.Coefficient = dataModel.Radio;
                        sel.PhyType = dataModel.IsSignal ? PhyType.信号量 : PhyType.模拟量;
                        sel = DecorateItem(sel);
                        _transmitDataItems.Add(sel);
                    }
                }
            }
            
        }
        private void BtnDelDataItem_OnClick(object sender, RoutedEventArgs e)
        {
            int count = _gridDataItem.SelectedItems.Count, index = 0;
            while (_gridDataItem.SelectedItems.Count > 0)
            {
                if (_gridDataItem.SelectedItems[0] is TransmitData del) _transmitDataItems.Remove(del);
                index++;
                if (index >= count)
                    break;
            }
        }
        private void MiUp_OnClick(object sender, RoutedEventArgs e)
        {
            if (_gridDataItem.SelectedItem is TransmitData sel)
            {
                int index = _transmitDataItems.IndexOf(sel);
                if (index > 0)
                    _transmitDataItems.Move(index, index - 1);
            }
            else
            {
                MessageBox.Show("请先选择数据项!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }
        private void MiDown_OnClick(object sender, RoutedEventArgs e)
        {
            if (_gridDataItem.SelectedItem is TransmitData sel)
            {
                int index = _transmitDataItems.IndexOf(sel);
                if (index < _transmitDataItems.Count - 1)
                    _transmitDataItems.Move(index, index + 1);
            }
            else
            {
                MessageBox.Show("请先选择数据项!", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }
        
        #endregion

        #region 导入导出数据项

        private void BtnExportDataItem_OnClick(object sender, RoutedEventArgs e)
        {
            ConfigManager.ExportTransmitDeviceConfig(_device, _transmitDataItems.ToList());
        }


        #endregion

        #region 数据项额外参数处理
        /// <summary>
        /// 将数据项额外参数序列化
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        private List<TransmitData> SerializeItems(List<TransmitData> items)
        {
            if (_devProtocols.ContainsKey(_device.Protocol)) 
            {
                items = _devProtocols[_device.Protocol].SerializeDataItems(items);
            }
            return items;
        }
        /// <summary>
        /// 将额外参数反序列化
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        private List<TransmitData> DeSerializeItems(List<TransmitData> items)
        {
            if (!_devProtocols.ContainsKey(_device.Protocol))   // 处理跟协议相关的数据项信息
            {
                TransmitDeviceProtocol protocol = _device.GetBaseDevProtocol();
                if (protocol != null)
                {
                    _devProtocols.Add(_device.Protocol, protocol);
                    items = protocol.DeSerializeDataItems(items);
                }
            }
            else
            {
                items = _devProtocols[_device.Protocol].DeSerializeDataItems(items);
            }
            return items;
        }

        /// <summary>
        /// 给数据项添加额外参数
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private TransmitData DecorateItem(TransmitData item)
        {
            if (_devProtocols.ContainsKey(_device.Protocol)) 
            {
                item = _devProtocols[_device.Protocol].DecorateItem(item);
            }
            return item;
        }
        #endregion

        private void CbbChannel_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _selectDevice = null;
            _selectChannel = cbbChannel.SelectedItem as Channel;
            _devices.Clear();
            if (_selectChannel != null)
            {
                List<Device> devices = AppManager.DeviceDao.GetDevicesByChlId(_selectChannel.Id);
                if (devices != null)
                {
                    foreach (Device dev in devices)
                    {
                        _devices.Add(dev);
                    }
                }

            }
            cbbDevice.ItemsSource = _devices;
        }

        private void CbbDevice_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _selectDataItem = null;
            _selectDevice = cbbDevice.SelectedItem as Device;
            _dataItems.Clear();
            if (_selectDevice != null)
            {
                List<DataItem> dataItems = AppManager.DataItemDao.GetDataItemsByDevId(_selectDevice.Id);
                if (dataItems != null)
                {
                    foreach (DataItem item in dataItems)
                    {
                        _dataItems.Add(item);
                    }
                }

            }
            cbbDataItem.ItemsSource = _dataItems;
            if (_dataItems.Count > 0)
                cbbDataItem.SelectedItem = _dataItems[_dataItems.Count - 1];
        }

        private void CbbDataItem_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            _selectDataItem = cbbDataItem.SelectedItem as DataItem;
            if (_selectDataItem != null&& _selectTransmitData!=null) _selectTransmitData.SourceId = _selectDataItem.Id;
        }

        private void _gridDataItem_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                _selectTransmitData = _gridDataItem.SelectedItem as TransmitData;
                if (_selectTransmitData == null) return;
                DataItem dataItem = AppManager.DataItemDao.GetEntityById(_selectTransmitData.SourceId);
                if (dataItem != null)
                {
                    Device device = AppManager.DeviceDao.GetEntityById(dataItem.DeviceId);
                    if (device != null)
                    {
                        Channel channel = _channels.FirstOrDefault(sss => sss.Id == device.ChannelId);
                        if (channel != null)
                        {
                            cbbChannel.SelectedItem = channel;
                            _devices.Clear();
                            List<Device> devices = AppManager.DeviceDao.GetDevicesByChlId(channel.Id);
                            if (devices != null)
                            {
                                foreach (Device dev in devices)
                                {
                                    _devices.Add(dev);
                                    if (dev.Id == device.Id)
                                        device = dev;
                                }
                            }
                            cbbDevice.ItemsSource = _devices;
                            cbbDevice.SelectedItem = device;
                            _dataItems.Clear();
                            List<DataItem> dataItems = AppManager.DataItemDao.GetDataItemsByDevId(device.Id);
                            if (dataItems != null)
                            {
                                foreach (DataItem item in dataItems)
                                {
                                    _dataItems.Add(item);
                                    if (item.Id == dataItem.Id)
                                        dataItem = item;
                                }
                            }
                            cbbDataItem.ItemsSource = _dataItems;
                            cbbDataItem.SelectedItem = dataItem;
                        }
                    }
                }
            }
            catch 
            {
            }
        }

       
    }

    public class HexConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!(value is Int32)) return "0000";
            int val = (int)value;
            return val.ToString("X04");
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null || string.IsNullOrEmpty(value.ToString())) return 0;
           return System.Convert.ToInt32(value.ToString(), 16);
        }
    }
}
